{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1引言"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "TensorFlow2.0版本已经发布，虽然不是正式版，但预览版都发布了，正式版还会远吗？相比于1.X，2.0版的TensorFlow修改的不是一点半点，这些修改极大的弥补了1.X版本的反人类设计，提升了框架的整体易用性，绝对好评！  \n",
    "\n",
    "赶紧来学习一波吧，做最先吃螃蟹的那一批人！先从TensorFlow的基本数据结构——张量（tensor）开始。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2 创建"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.1 constant()方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=0, shape=(), dtype=int32, numpy=1>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.constant(1)  # 创建一个整型张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=2, shape=(), dtype=float32, numpy=1.0>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.constant(1.)  # 创建一个浮点型张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=4, shape=(), dtype=float64, numpy=2.0>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.constant(2., dtype=tf.double)  # 创建的同时指定数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=6, shape=(2, 3), dtype=float32, numpy=\n",
       "array([[1., 2., 3.],\n",
       "       [4., 5., 6.]], dtype=float32)>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.constant([[1.,2.,3.],[4.,5.,6.]])  # 通过传入一个list参数创建"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果输入的数据与指定的数据类型不相符，会产生以下异常：  \n",
    "TypeError: Cannot convert provided value to EagerTensor. Provided value: 2.1 Requested dtype: int32"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.2 convert_to_tensor()方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=9, shape=(2, 3), dtype=float64, numpy=\n",
       "array([[1., 1., 1.],\n",
       "       [1., 1., 1.]])>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.convert_to_tensor(np.ones([2, 3]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=11, shape=(2, 3), dtype=float64, numpy=\n",
       "array([[1., 1., 1.],\n",
       "       [1., 1., 1.]])>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.convert_to_tensor(np.ones([2, 3]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=13, shape=(2, 2), dtype=float32, numpy=\n",
       "array([[2., 3.],\n",
       "       [3., 4.]], dtype=float32)>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.convert_to_tensor([[2.,3.],[3., 4.]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.3 创建元素为指定值的tensor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果你熟悉numpy创建数组的方法，你一定见过zeros()、ones()等方法，TensorFlow中也有这些方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**（1）zeros()与ones()**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = tf.zeros([2, 3, 3])  # 创建一个元素全为0，形状为[2, 3, 3]的tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=46, shape=(2, 3, 3), dtype=float32, numpy=\n",
       "array([[[0., 0., 0.],\n",
       "        [0., 0., 0.],\n",
       "        [0., 0., 0.]],\n",
       "\n",
       "       [[0., 0., 0.],\n",
       "        [0., 0., 0.],\n",
       "        [0., 0., 0.]]], dtype=float32)>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = tf.ones([2, 3])  #  创建一个元素全为1，形状为[2, 3]的tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=50, shape=(2, 3), dtype=float32, numpy=\n",
       "array([[1., 1., 1.],\n",
       "       [1., 1., 1.]], dtype=float32)>"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**（2）zeros_like()与ones_like**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=52, shape=(2, 3), dtype=float32, numpy=\n",
       "array([[0., 0., 0.],\n",
       "       [0., 0., 0.]], dtype=float32)>"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.zeros_like(b)  # 仿照b的shape创建一个全为0的tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=56, shape=(2, 3, 3), dtype=float32, numpy=\n",
       "array([[[1., 1., 1.],\n",
       "        [1., 1., 1.],\n",
       "        [1., 1., 1.]],\n",
       "\n",
       "       [[1., 1., 1.],\n",
       "        [1., 1., 1.],\n",
       "        [1., 1., 1.]]], dtype=float32)>"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.ones_like(a)  # 仿照b的shape创建一个全为1的tensor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**（3）fill()**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=38, shape=(2, 3), dtype=int32, numpy=\n",
       "array([[5, 5, 5],\n",
       "       [5, 5, 5]])>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.fill([2,3],5)  # 创建元素全为5，形状为[2,3]的tensor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.4 随机初始化"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在实际应用中，经常需要随机初始化元素服从某种分布的tensor，TensorFlow中也提供了这种功能。  \n",
    "\n",
    "**（1）从指定正态分布中随机取值：tf.random.normal()。**例如，随机初始化一个元素服从均值为1，方差为1的正态分布且形状为[2, 3]的tensor："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=63, shape=(2, 3), dtype=float32, numpy=\n",
       "array([[ 1.7034731 ,  0.4979009 ,  1.4266468 ],\n",
       "       [-0.33414853,  0.2618034 ,  0.3966313 ]], dtype=float32)>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.random.normal([2, 3], mean=1, stddev=1) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**（2）从指定的截断正态分布中随机取值：truncated_normal()。**意思是从指定的正太分布中取值，但是取值范围在两个标准差范围内，也就是：[ mean - 2 * stddev, mean + 2 * stddev ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=70, shape=(2, 3), dtype=float32, numpy=\n",
       "array([[0.71736836, 1.7930655 , 0.47575486],\n",
       "       [0.83504593, 0.7969478 , 0.6002228 ]], dtype=float32)>"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.random.truncated_normal([2, 3], mean=1, stddev=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**（3）从指定均匀分布中随机取值：tf.random.uniform()。**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=78, shape=(2, 3), dtype=float32, numpy=\n",
       "array([[1.7117869, 1.2625391, 1.6652637],\n",
       "       [1.3810604, 1.0297629, 1.1268978]], dtype=float32)>"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.random.uniform([2, 3], minval=1, maxval=2) # 在1~2之间均匀分布"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3 索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = tf.convert_to_tensor(np.arange(80).reshape(2,2,4,5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=80, shape=(2, 2, 4, 5), dtype=int32, numpy=\n",
       "array([[[[ 0,  1,  2,  3,  4],\n",
       "         [ 5,  6,  7,  8,  9],\n",
       "         [10, 11, 12, 13, 14],\n",
       "         [15, 16, 17, 18, 19]],\n",
       "\n",
       "        [[20, 21, 22, 23, 24],\n",
       "         [25, 26, 27, 28, 29],\n",
       "         [30, 31, 32, 33, 34],\n",
       "         [35, 36, 37, 38, 39]]],\n",
       "\n",
       "\n",
       "       [[[40, 41, 42, 43, 44],\n",
       "         [45, 46, 47, 48, 49],\n",
       "         [50, 51, 52, 53, 54],\n",
       "         [55, 56, 57, 58, 59]],\n",
       "\n",
       "        [[60, 61, 62, 63, 64],\n",
       "         [65, 66, 67, 68, 69],\n",
       "         [70, 71, 72, 73, 74],\n",
       "         [75, 76, 77, 78, 79]]]])>"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.1 基础索引"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "TensorFlow支持Python原生的基础索引方式，即多个方括号逐步索引取值：[idx][idx][idx]，每个方括号对应一个维度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=85, shape=(2, 4, 5), dtype=int32, numpy=\n",
       "array([[[ 0,  1,  2,  3,  4],\n",
       "        [ 5,  6,  7,  8,  9],\n",
       "        [10, 11, 12, 13, 14],\n",
       "        [15, 16, 17, 18, 19]],\n",
       "\n",
       "       [[20, 21, 22, 23, 24],\n",
       "        [25, 26, 27, 28, 29],\n",
       "        [30, 31, 32, 33, 34],\n",
       "        [35, 36, 37, 38, 39]]])>"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[0]  # 取第一个维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=94, shape=(4, 5), dtype=int32, numpy=\n",
       "array([[20, 21, 22, 23, 24],\n",
       "       [25, 26, 27, 28, 29],\n",
       "       [30, 31, 32, 33, 34],\n",
       "       [35, 36, 37, 38, 39]])>"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[0][1]  # 同时筛选两个维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=111, shape=(), dtype=int32, numpy=38>"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[0][1][3][3]  # 同时对4个维度进行筛选"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这种索引数据的方法简单，易于理解，但是可读性差，只能按维度依次索引数据，也不能索引列。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.2 numpy索引"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "TensorFlow也继承了numpy中的部分索引方式，如果对numpy索引方式不熟悉，可以查看我的[前几篇博客](https://www.cnblogs.com/chenhuabin/p/11412818.html)。  \n",
    "**（1）[idx1, idx2, idx3]**  \n",
    "这种索引方式是在一个方括号内写下所有的索引，每个索引序号之间用逗号隔开。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=116, shape=(2, 4, 5), dtype=int32, numpy=\n",
       "array([[[40, 41, 42, 43, 44],\n",
       "        [45, 46, 47, 48, 49],\n",
       "        [50, 51, 52, 53, 54],\n",
       "        [55, 56, 57, 58, 59]],\n",
       "\n",
       "       [[60, 61, 62, 63, 64],\n",
       "        [65, 66, 67, 68, 69],\n",
       "        [70, 71, 72, 73, 74],\n",
       "        [75, 76, 77, 78, 79]]])>"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1]  # 筛选第一维度，这跟基础索引一样"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=121, shape=(5,), dtype=int32, numpy=array([75, 76, 77, 78, 79])>"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1,1, 3]  # 同时帅选3个维度"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**（2）冒号切片与步长：[start:end:step]**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这种索引方式在Python原生的list类型中也是常见的，而且使用方法也是一样的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=126, shape=(2, 2, 5), dtype=int32, numpy=\n",
       "array([[[40, 41, 42, 43, 44],\n",
       "        [45, 46, 47, 48, 49]],\n",
       "\n",
       "       [[60, 61, 62, 63, 64],\n",
       "        [65, 66, 67, 68, 69]]])>"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1,:,0:2] # 对第1维度选第二块数据，对第二维度选所有数据，对第三维度选前两行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=131, shape=(2, 2, 4), dtype=int32, numpy=\n",
       "array([[[40, 41, 42, 43],\n",
       "        [45, 46, 47, 48]],\n",
       "\n",
       "       [[60, 61, 62, 63],\n",
       "        [65, 66, 67, 68]]])>"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1,:,0:2,0:4] # 继续上面的例子，对第4维度筛选去前4列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=136, shape=(2, 2, 2), dtype=int32, numpy=\n",
       "array([[[40, 42],\n",
       "        [45, 47]],\n",
       "\n",
       "       [[60, 62],\n",
       "        [65, 67]]])>"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1,:,0:2,0:4:2] # 对第4维度加上步长，每隔一个数据取一次"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "也可以使用负值步长表示逆序索引，但要注意，负数步长时，原本的[start : end : step]也要跟着编程[end : start : step]："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=141, shape=(2, 2, 4), dtype=int32, numpy=\n",
       "array([[[44, 43, 42, 41],\n",
       "        [49, 48, 47, 46]],\n",
       "\n",
       "       [[64, 63, 62, 61],\n",
       "        [69, 68, 67, 66]]])>"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1,:,0:2,4:0:-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=146, shape=(2, 2, 2), dtype=int32, numpy=\n",
       "array([[[44, 42],\n",
       "        [49, 47]],\n",
       "\n",
       "       [[64, 62],\n",
       "        [69, 67]]])>"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1,:,0:2,4:0:-2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在numpy和TensorFlow中还有“...\"（三个英文句号）的使用，“...\"用于表示连续多个维度全选："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=151, shape=(2, 4, 4), dtype=int32, numpy=\n",
       "array([[[40, 41, 42, 43],\n",
       "        [45, 46, 47, 48],\n",
       "        [50, 51, 52, 53],\n",
       "        [55, 56, 57, 58]],\n",
       "\n",
       "       [[60, 61, 62, 63],\n",
       "        [65, 66, 67, 68],\n",
       "        [70, 71, 72, 73],\n",
       "        [75, 76, 77, 78]]])>"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1,...,0:4] # 等同于a[1, : , : ,0:4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=156, shape=(4, 5), dtype=int32, numpy=\n",
       "array([[ 0,  1,  2,  3,  4],\n",
       "       [ 5,  6,  7,  8,  9],\n",
       "       [10, 11, 12, 13, 14],\n",
       "       [15, 16, 17, 18, 19]])>"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[0,0,...] # 等同于a[0,0,:,:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.3 gather与gather_nd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "gather与gather_nd是指TensorFlow通过gather()方法和gather_nd()方法提供的两种索引方式。在numpy中，可以通过嵌套list的方式来指定无规则的索引："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.arange(20).reshape(4,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 8, 9])"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[1, [0,3,4]] # 选取第2行的第1列、第4列、第5列"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但是在TensorFlow中，这种索引方式并没有从numpy中继承下来,所以如果在Tensor中使用这种方式，会抛出以下异常：  \n",
    "TypeError: Only integers, slices (`:`), ellipsis (`...`), tf.newaxis (`None`) and scalar tf.int32/tf.int64 tensors are valid indices, got [0, 3, 4]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "还好的是，在TensorFlow中通过gather()方法和gather_nd()方法提供了这种索引方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**（1）gather()方法**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=163, shape=(3, 5), dtype=int32, numpy=\n",
       "array([[ 0,  1,  2,  3,  4],\n",
       "       [10, 11, 12, 13, 14],\n",
       "       [15, 16, 17, 18, 19]])>"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.gather(b, axis=0, indices=[0, 2, 3]) # 选取第1行，第3行，第4行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=168, shape=(4, 3), dtype=int32, numpy=\n",
       "array([[ 0,  2,  3],\n",
       "       [ 5,  7,  8],\n",
       "       [10, 12, 13],\n",
       "       [15, 17, 18]])>"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.gather(b, axis=1, indices=[0, 2, 3]) # 选取第1列，第3列，第4列"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "仔细观察上面gather()方法例子，可以发现，第一个参数时数据源，还有两个参数中，axis指的是将要的维度，indices指的是需要选取的序号。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**（2）gather_nd()**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "gather()方法一次只能对一个维度进行索引，gather_nd()方法可以同时对多个维度进行索引。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=172, shape=(2,), dtype=int32, numpy=array([ 2, 18])>"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.gather_nd(b, [[0, 2],[3, 3]]) # 选取第1行第3列的那个数据，和第4行第4列的数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.5 条件索引"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以结合一些简单的逻辑运算符进行索引取值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=17, shape=(3, 3), dtype=int32, numpy=\n",
       "array([[-7, -9,  6],\n",
       "       [-6, -5,  9],\n",
       "       [ 8,  9,  4]])>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = tf.random.uniform([3,3],minval=-10,maxval=10,dtype=tf.int32)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=20, shape=(3, 3), dtype=bool, numpy=\n",
       "array([[ True,  True, False],\n",
       "       [ True,  True, False],\n",
       "       [False, False, False]])>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mask = a < 0\n",
    "mask"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，返回的是一个shape与a相同的tensor，在a小于零的位置是True，大于零的位置为False。进一步地，我们可以用boolwan_mask()方法直接取出符合条件的元素："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=82, shape=(4,), dtype=int32, numpy=array([-7, -9, -6, -5])>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.boolean_mask(a,mask)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以结合where()方法取出符合条件元素的索引："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=84, shape=(4, 2), dtype=int64, numpy=\n",
       "array([[0, 0],\n",
       "       [0, 1],\n",
       "       [1, 0],\n",
       "       [1, 1]], dtype=int64)>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m_index = tf.where(mask)\n",
    "m_index"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "再使用之前说过的gather_nd()方法取值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=86, shape=(4,), dtype=int32, numpy=array([-7, -9, -6, -5])>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.gather_nd(a,m_index)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "where()方法还有第二种用法——从两个tensor中取出符合条件的值，这时候where()方法必须接受3个参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=124, shape=(3, 3), dtype=bool, numpy=\n",
       "array([[ True,  True, False],\n",
       "       [ True, False, False],\n",
       "       [ True, False, False]])>"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "condition = tf.random.uniform([3,3],minval=0,maxval=2,dtype=tf.int32)\n",
    "condition = tf.cast(condition, tf.bool)\n",
    "condition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=162, shape=(3, 3), dtype=int32, numpy=\n",
       "array([[1, 2, 3],\n",
       "       [4, 5, 6],\n",
       "       [7, 8, 9]])>"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = tf.range(1,10)\n",
    "a = tf.reshape(a,[3,3])\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=169, shape=(3, 3), dtype=int32, numpy=\n",
       "array([[-9, -8, -7],\n",
       "       [-6, -5, -4],\n",
       "       [-3, -2, -1]])>"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = tf.range(-9,0)\n",
    "b = tf.reshape(b,[3,3])\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=171, shape=(3, 3), dtype=int32, numpy=\n",
       "array([[ 1,  2, -7],\n",
       "       [ 4, -5, -4],\n",
       "       [ 7, -2, -1]])>"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.where(condition, a, b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上面where()方法返回的结果在True的位置取值是a中对应位置元素的值，在False位置是b中对应元素的值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4 维度变换"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.1 reshape()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "numpy中的ndarray数组有个一reshape()方法，用来改变数组的shape，TensorFlow中的reshape()方法，功能也是一样的，不过TensorFlow中的reshape()没有绑定到tensor中："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = tf.ones([2,3,4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TensorShape([2, 3, 4])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=176, shape=(2, 3, 4), dtype=float32, numpy=\n",
       "array([[[1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1.]],\n",
       "\n",
       "       [[1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1.]]], dtype=float32)>"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = tf.reshape(a, [2, 2, 6])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TensorShape([2, 2, 6])"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=179, shape=(2, 2, 6), dtype=float32, numpy=\n",
       "array([[[1., 1., 1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1., 1., 1.]],\n",
       "\n",
       "       [[1., 1., 1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1., 1., 1.]]], dtype=float32)>"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "c = tf.reshape(a, [3, 2, 4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=183, shape=(3, 2, 4), dtype=float32, numpy=\n",
       "array([[[1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1.]],\n",
       "\n",
       "       [[1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1.]],\n",
       "\n",
       "       [[1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1.]]], dtype=float32)>"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，在上面的例子中，通过reshape()方法可以很方便的改变tensor的形状，得到一个新的tensor，需要注意的是在进行维度变换时，数据的重量是不变的，上面的例子无论是[2,3,4]， [2, 2, 6]还是[3, 2, 4]都对应总量24，如果对应不上，就会产生异常。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.2 转置：transpose()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "transpose()方法提供了一种类似于装置的操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = tf.constant([[1,2,3],[4,5,6]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TensorShape([2, 3])"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = tf.transpose(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TensorShape([3, 2])"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=192, shape=(3, 2), dtype=int32, numpy=\n",
       "array([[1, 4],\n",
       "       [2, 5],\n",
       "       [3, 6]])>"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在默认情况下，transpose()方法会将所有维度按逆序方式完全转置，当然也可以通过perm参数执行需要转置的维度："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [],
   "source": [
    "a=tf.constant([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=194, shape=(2, 2, 3), dtype=int32, numpy=\n",
       "array([[[ 1,  2,  3],\n",
       "        [ 4,  5,  6]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])>"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = tf.transpose(a) # 不指定perm参数时，相当于tf.transpose(a, perm=[2, 1, 0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=197, shape=(3, 2, 2), dtype=int32, numpy=\n",
       "array([[[ 1,  7],\n",
       "        [ 4, 10]],\n",
       "\n",
       "       [[ 2,  8],\n",
       "        [ 5, 11]],\n",
       "\n",
       "       [[ 3,  9],\n",
       "        [ 6, 12]]])>"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [],
   "source": [
    "c = tf.transpose(a, perm=[2, 1, 0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=200, shape=(3, 2, 2), dtype=int32, numpy=\n",
       "array([[[ 1,  7],\n",
       "        [ 4, 10]],\n",
       "\n",
       "       [[ 2,  8],\n",
       "        [ 5, 11]],\n",
       "\n",
       "       [[ 3,  9],\n",
       "        [ 6, 12]]])>"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [],
   "source": [
    "d = tf.transpose(a, perm=[0, 2, 1]) # 第一个维度不做变换，对第二、第三维度进行转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=203, shape=(2, 3, 2), dtype=int32, numpy=\n",
       "array([[[ 1,  4],\n",
       "        [ 2,  5],\n",
       "        [ 3,  6]],\n",
       "\n",
       "       [[ 7, 10],\n",
       "        [ 8, 11],\n",
       "        [ 9, 12]]])>"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.3 添加维度：expand_dims()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [],
   "source": [
    "a=tf.constant([[1,2,3],[4,5,6]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=205, shape=(2, 3), dtype=int32, numpy=\n",
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])>"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=208, shape=(1, 2, 3), dtype=int32, numpy=\n",
       "array([[[1, 2, 3],\n",
       "        [4, 5, 6]]])>"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.expand_dims(a, axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=211, shape=(2, 1, 3), dtype=int32, numpy=\n",
       "array([[[1, 2, 3]],\n",
       "\n",
       "       [[4, 5, 6]]])>"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.expand_dims(a, axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=214, shape=(2, 3, 1), dtype=int32, numpy=\n",
       "array([[[1],\n",
       "        [2],\n",
       "        [3]],\n",
       "\n",
       "       [[4],\n",
       "        [5],\n",
       "        [6]]])>"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.expand_dims(a, axis=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=217, shape=(2, 3, 1), dtype=int32, numpy=\n",
       "array([[[1],\n",
       "        [2],\n",
       "        [3]],\n",
       "\n",
       "       [[4],\n",
       "        [5],\n",
       "        [6]]])>"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.expand_dims(a, axis=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "expand_dims()方法添加维度时，通过axis参数指定添加维度的位置，正数表示从前往后数，负数表示从后往前数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.4 压缩维度：squeeze()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "squeeze()方法与expand_dims()方法作用刚好相反，其作用是删除张量中dim为1的维度："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = tf.ones([1,3,1,2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=221, shape=(1, 3, 1, 2), dtype=float32, numpy=\n",
       "array([[[[1., 1.]],\n",
       "\n",
       "        [[1., 1.]],\n",
       "\n",
       "        [[1., 1.]]]], dtype=float32)>"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=223, shape=(3, 2), dtype=float32, numpy=\n",
       "array([[1., 1.],\n",
       "       [1., 1.],\n",
       "       [1., 1.]], dtype=float32)>"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.squeeze(a)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "tensorflow_gpu",
   "language": "python",
   "name": "tensorflow_gpu"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
